<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Route;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Tymon\JWTAuth\Facades\JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
use functions;

class AuthJWT extends BaseMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        try {
            /**
             *
             *TODO 获取用户信息的方法可封装起来
             *对应的放回参数可根据个人习惯进行自定义
             */
            $this->checkForToken($request);

            $token = JWTAuth::getToken();

            if ($token) {
                JWTAuth::setToken($token);
            }

            if (!$user = JWTAuth::toUser()) {
                return Failed(40004, ["File" => "AuthJWT", "Line" => __LINE__]);
            }


        } catch (TokenExpiredException $e) {
            return Failed(40003, ["File" => "AuthJWT", "Line" => __LINE__]);
        } catch (TokenInvalidException $e) {
            return Failed(40001, ["File" => "AuthJWT", "Line" => __LINE__]);
        } catch (JWTException $e) {
            return Failed(40500, ["File" => "AuthJWT", "Line" => __LINE__]);
        }catch (UnauthorizedHttpException $e){
            return Failed(401, ["File" => "AuthJWT", "Line" => __LINE__]);
        }

        //超级管理员 绕过权限
        if ($user->is_supper_admin == 1) {
            return $next($request);
        }

        return $this->checkUserPermission($user, $next, $request);


    }

    /**
     * 检查用户权限 通过放行
     * @param $user
     * @param $next
     * @param $request
     * @return \Illuminate\Http\JsonResponse
     */
    protected function checkUserPermission($user, $next, $request): \Illuminate\Http\JsonResponse
    {
        $permission = self::getUserPermissionAndMenu($user)['permission'];
        $token = JWTAuth::getToken(); //可以换成接受到的token,  JWTAuth::setToken($token)
        $payload = JWTAuth::manager()->getJWTProvider()->decode($token->get());
        $user_per = json_decode(json_encode($payload['extra_permission'], true), true);
        foreach ($user_per as $key=>$vo){
            $permission[$key] = $vo;

        }

        $res = [];

        foreach ($permission as $key => $vo) {
            if (!$vo['api_route']) {
                $res[$key] = null;
            } else {
                $res[$key] = $vo['method'].".".$vo['api_route'];
            }

        }

        $method = $request->method();
        $url = substr($request->getPathInfo(), 1);
        if (!in_array($method.".".$url, $res)) {
            return Failed(30001, ["File" => "AuthJWT", "Line" => __LINE__, "AccessBan" => $url]);
        } else {
            $exit = array_flip(array_filter($res));
            $permission_id = $exit[$method.".".$url];
            $permission_info = $permission[$permission_id];
            if ($permission_info['is_need_auth'] == 1) {
                if ($permission_info["method"]!= $method) {
                    return Failed(30002,
                        ["File" => "AuthJWT", "Line" => __LINE__, "AllowMethod" => $permission_info["method"]]);
                }
            }
        }
        return $next($request);
    }

    /**
     * 获取当前用户的权限和菜单
     * @param $user
     * @return array[]
     */
    protected function getUserPermissionAndMenu($user): array
    {
        $user_role_per = $user->roles[0]->with([
            "permissions" => function ($query) {
                $query->select('permission.id as per_id', 'parentid', 'name', 'api_route', 'web_route', 'method', 'no',
                    'is_need_auth', 'is_system_menu', 'status');
                $query->where("status", 1);
                $query->where("is_need_auth", 1);
            }
        ])->get()->toArray();
        $permissions = [];
        $menu = [];

        foreach ($user_role_per as $vo) {
            if (!empty($vo['permissions'])) {

                foreach ($vo['permissions'] as $v) {
                    $permissions[$v['per_id']] = $v;
                    if ($v['is_system_menu'] == 1) {
                        $menu[$v['per_id']] = $v;
                    }
                }
            }
        }

        return ["permission" => $permissions, "menu" => $menu];
    }

    /**
     * 获取当前用户的角色组
     * @param $user
     * @return array
     */
    protected function getUserRoles($user): array
    {

        $userInfo = $user->with([
            'roles' => function ($query) {
                $query->select("name as role_name");
                $query->where("status", 1);
            }
        ])->first()->toArray();

        return Arr::pluck($userInfo['roles'], 'role_name');

    }
}







